package com.inspectortime.webapp;

import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.type.InspectionStatus;
import com.inspectortime.repository.Factory;
import com.inspectortime.repository.Repository;
import com.inspectortime.webapp.util.HttpSessionUtils;

public class RetrieveIncompleteInspectionController extends
		SimpleFormController {

	private static Log log = LogFactory.getLog(RetrieveIncompleteInspectionController.class);
	
	private Factory factory;

	private Repository repository;
	
	/**
	 * min delta time between the scheduled inspection and now in hours
	 */
	private int inspectionExpirationTimeDelta = 12;

	protected Object formBackingObject(HttpServletRequest request)
			throws Exception {

		Inspection inspection = factory.createInspection();
		return inspection;
	}

	
	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {

		Inspection inspection = (Inspection) command;
		log.debug("Retrieving inpection with code: " + inspection.getInspectionCode());

		Inspection retrievedInspection = repository.findInspectionByCode(inspection.getInspectionCode());

		validateForm(errors, inspection, retrievedInspection);
		
		ModelAndView mav;
		if (errors.hasErrors()){
			mav = showForm(request, response, errors);
		} else {
			HttpSessionUtils.storeWizardInspection(request, retrievedInspection.getId());
			mav = new ModelAndView(getSuccessView() + "?inspectorId=" + retrievedInspection.getInspector().getId());
		}
		
		return mav;
	}


	private void validateForm(BindException errors, Inspection inspection,
			Inspection retrievedInspection) {
		
		if (retrievedInspection == null) {
			log.debug("InvalidInspection - retrievedInspection not found");
			errors.reject("retrieveInspection.inspection.notFound");
			return;
		}
		
		if (retrievedInspection.getInspectionStatus() == InspectionStatus.COMPLETED || retrievedInspection.getInspectionStatus() == InspectionStatus.SCHEDULED) {
			log.debug("InvalidInspection - retrievedInspection status: " + retrievedInspection.getInspectionStatus());
			errors.reject("retrieveInspection.inspection.invalid");
			return;
		}
		
		if (isInspectionExpired(retrievedInspection)){
			log.debug("InvalidInspection - isInspectionExpired: " + isInspectionExpired(retrievedInspection)); 
			errors.reject("retrieveInspection.inspection.expired");
			return;
		}
	
		if (!StringUtils.hasText(inspection.getHomeBuyer().getName().getFirst())){
			errors.rejectValue("homeBuyer.name.first", "retrieveInspection.homeBuyer.firstName.empty");
		} else if (!inspection.getHomeBuyer().getName().getFirst().equalsIgnoreCase(retrievedInspection.getHomeBuyer().getName().getFirst())) {
			errors.rejectValue("homeBuyer.name.first", "retrieveInspection.homeBuyer.firstName.incorrect");
		}
		
		if (!StringUtils.hasText(inspection.getHomeBuyer().getName().getLast())){
			errors.rejectValue("homeBuyer.name.last", "retrieveInspection.homeBuyer.lastName.empty");
		} else if (!inspection.getHomeBuyer().getName().getLast().equalsIgnoreCase(retrievedInspection.getHomeBuyer().getName().getLast())) {
			errors.rejectValue("homeBuyer.name.last", "retrieveInspection.homeBuyer.lastName.incorrect");
		}	
		
		if (!StringUtils.hasText(inspection.getHomeBuyer().getOtherPhone())){
			errors.rejectValue("homeBuyer.otherPhone", "retrieveInspection.homeBuyer.phone.empty");
		} else if (!inspection.getHomeBuyer().getOtherPhone().equalsIgnoreCase(retrievedInspection.getHomeBuyer().getOtherPhone())) {
			errors.rejectValue("homeBuyer.otherPhone", "retrieveInspection.homeBuyer.phone.incorrect");
		}	
		
	}

	private boolean isInspectionExpired(Inspection retrievedInspection) {

		// let's create a time instance, add the time delta and verify 
		// that the inspection is schedule for a date after it
		Calendar cal = Calendar.getInstance();
		cal.setLenient(true);
		cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + inspectionExpirationTimeDelta);
		
		log.debug("Cal: " + cal.toString() + " - inspection: " + retrievedInspection.getInspectionTime().toString());
		
		return retrievedInspection.getInspectionTime().before(cal.getTime()); // it's expired
	}


	public void setFactory(Factory factory) {
		this.factory = factory;
	}

	public void setRepository(Repository repository) {
		this.repository = repository;
	}


	public void setInspectionExpirationTimeDelta(int inspectionExpirationTimeDelta) {
		this.inspectionExpirationTimeDelta = inspectionExpirationTimeDelta;
	}

}
